package registration;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.ConnectException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.List;

import javax.net.ssl.SSLSocket;
import javax.swing.SwingWorker;

import prevote.PreVotePanelDescriptor;
import protocol.Info;
import sslsockets.SSLSocketHandler;
import wizard.Wizard;
import wizard.WizardPanelDescriptor;

public class RegistrationCompletePanelDescriptor extends WizardPanelDescriptor
{
    private class ServerConnectionHandler extends SwingWorker<Boolean, String>
    {
        public ServerConnectionHandler()
        {
        }

        @Override
        protected Boolean doInBackground()
        {
            publish( "Connecting to the server..." );
            Boolean result = new Boolean( false );
            try
            {
                KeyStore trustKeyStore = KeyStore.getInstance( KeyStore.getDefaultType() );
                KeyStore keyStore = KeyStore.getInstance( KeyStore.getDefaultType() );
                FileInputStream fis = new FileInputStream( trustKeyStoreFile );
                trustKeyStore.load( fis, trustKeyStorePassword );
                fis.close();
                fis = new FileInputStream( keyStoreFile );
                keyStore.load( fis, keyStorePassword );
                SSLSocket sslSocket = SSLSocketHandler.createSocket( Info.HOSTIN, Info.REGISTRATION_PORT, trustKeyStore, keyStore, data
                        .getsecretCode().toCharArray() );
                publish( "Connected to the server" );
                OutputStream out = sslSocket.getOutputStream();
                ObjectOutputStream oout = new ObjectOutputStream( out );
                publish( "Sending data for validation." );
                oout.writeObject( data );
                publish( "Sending certificate." );
                Certificate cert = keyStore.getCertificate( data.getpesel() );
                oout.writeObject( cert );
                publish( "Certificate sent." );
                InputStream in = sslSocket.getInputStream();
                ObjectInputStream oin = new ObjectInputStream( in );
                Object received = null;
                try
                {
                    received = oin.readObject();
                }
                catch( Exception e )
                {
                    publish( "<html>There has been a problem with a connection to PKW.<br>Check your Internet connection and try again.</html>" );
                    return result;
                }
                if( received instanceof String )
                {
                    if( ( (String)received ).equals( Info.MSG_REG_FAIL ) )
                    {
                        publish( Info.MSG_REG_FAIL );
                        return result;
                    }
                    if( ( (String)received ).equals( Info.MSG_ALL_GOOD ) )
                    {
                        publish( "Validation completed." );
                        getWizard().setNextFinishButtonEnabled( true );
                    }
                }
                // if( received instanceof Certificate )
                // {
                // publish("Validation success.");
                // // zapisujemy certyfikat ktory dostalismy od PKW
                //
                // // a sprobujmy zapisac go w tym samym pliku co ten pierwszy
                // certyfikat
                // // X509Certificate userPKWCert = (X509Certificate)received;
                // // keyStore.setCertificateEntry("PKW", userPKWCert);
                // // FileOutputStream fos = new FileOutputStream(keyStoreFile);
                // // keyStore.store(fos, keyStorePassword);
                // // publish("Your certificate signed by PKW stored in " +
                // keyStoreFile);
                //
                // File userPKWCertKeyStore = null;
                // JFileChooser chooser = new JFileChooser();
                // chooser.setDialogTitle( "Save PKW Certificate" );
                // int returnVal = chooser.showSaveDialog(
                // getWizard().getDialog() );
                // if( returnVal == JFileChooser.APPROVE_OPTION )
                // {
                // userPKWCertKeyStore = chooser.getSelectedFile();
                // if( !userPKWCertKeyStore.getPath().isEmpty() )
                // {
                // KeyStore ks = KeyStore.getInstance( KeyStore.getDefaultType()
                // );
                // fis = new FileInputStream(userPKWCertKeyStore);
                // ks.load( null, data.getsecretCode().toCharArray() );
                // X509Certificate userPKWCert = (X509Certificate)received;
                // // we save a keystore object with a pesel as an
                // // identifier string and
                // // secret code as a password
                // ks.setCertificateEntry( data.getpesel(), userPKWCert );
                // FileOutputStream foStream = new FileOutputStream(
                // userPKWCertKeyStore );
                // ks.store( foStream, data.getsecretCode().toCharArray() );
                // getWizard().setNextFinishButtonEnabled( true );
                // }
                // }
                // }
                // server zwrocil cos innego niz String || Certificate -
                // niemozliwe
                else
                {
                    publish( "There has been a problem with the PKW server. Please try again." );
                    return result;
                }
                sslSocket.close();
                oout.close();
                fis.close();
                oin.close();
            }
            catch( ConnectException e )
            {
                publish( "<html>There has been a problem with a connection to PKW.<br>Check your Internet connection and try again.</html>" );
                e.printStackTrace();
            }
            catch( KeyStoreException e )
            {
                e.printStackTrace();
                getWizard().close( Wizard.ERROR_RETURN_CODE );
            }
            catch( FileNotFoundException e )
            {
                e.printStackTrace();
                getWizard().close( Wizard.ERROR_RETURN_CODE );
            }
            catch( NoSuchAlgorithmException e )
            {
                e.printStackTrace();
                getWizard().close( Wizard.ERROR_RETURN_CODE );
            }
            catch( CertificateException e )
            {
                e.printStackTrace();
                getWizard().close( Wizard.ERROR_RETURN_CODE );
            }
            catch( IOException e )
            {
                e.printStackTrace();
                getWizard().close( Wizard.ERROR_RETURN_CODE );
            }
            catch( UnrecoverableKeyException e )
            {
                e.printStackTrace();
                getWizard().close( Wizard.ERROR_RETURN_CODE );
            }
            result = new Boolean( true );
            return result;
        }

        public void process( List<String> communicates )
        {
            String infoText = "";
            for( String s: communicates )
            {
                infoText += ( s + "<br>" );
            }
            infoText += "";
            rcp.setInfoText( infoText );
        }
    }

    public static final String IDENTIFIER = "REGISTRATION_COMPLETE_PANEL";
    private String trustKeyStoreFile;
    private String keyStoreFile;
    private char[] trustKeyStorePassword;
    private char[] keyStorePassword;
    private RegistrationCompletePanel rcp;
    private PersonalData data;

    public RegistrationCompletePanelDescriptor()
    {
        rcp = new RegistrationCompletePanel();
        setPanelDescriptorIdentifier( IDENTIFIER );
        setPanelComponent( rcp );
    }

    @Override
    public void aboutToDisplayPanel()
    {
        getWizard().setBackButtonEnabled( false );
        getWizard().setNextFinishButtonEnabled( false );
        data = (PersonalData)getWizard().getPanelData( getBackPanelDescriptor() + "PersonalData" );
        keyStoreFile = (String)getWizard().getPanelData( getBackPanelDescriptor() + "keyStorePath" );
        if( data == null || keyStoreFile == null )
        {
            System.out.println( "Error getting PersonalData/keyStoreFile" );
            getWizard().close( Wizard.ERROR_RETURN_CODE );
        }
        RegistrationResources resources = new RegistrationResources();
        trustKeyStoreFile = (String)resources.getObject( "trustKeyStoreFile" );
        trustKeyStorePassword = (char[])resources.getObject( "trustKeyStorePassword" );
        keyStorePassword = data.getsecretCode().toCharArray();
    }

    @Override
    public void displayingPanel()
    {
        // sendDataToServer();
        ServerConnectionHandler sch = new ServerConnectionHandler();
        sch.execute();
    }

    public String getNextPanelDescriptor()
    {
        return PreVotePanelDescriptor.IDENTIFIER;
    }

    public String getBackPanelDescriptor()
    {
        return PersonalDataPanelDescriptor.IDENTIFIER;
    }
}